# -*- coding: utf-8 -*-
"""
Created on Sat Oct 23 15:49:13 2021

@author: leonardo.w
"""




import pandas as pd
import numpy as np


class SARIndicator():
    # def __init__(self, high: pd.Series, low: pd.Series, close: pd.Series, period: int = 4,
    #               step: float = 0.02,  max_step: float = 0.20, fillna: bool = False):
    def __init__(self, df, period = 4,
                  step = 0.02,  max_step= 0.20, fillna: bool = False):
        self._high = df['high'].copy()
        self._low = df['low'].copy()
        self._close = df['close'].copy()
        self._length = self._close.__len__()
        self._period = period - 1
        self._step = step
        self._max_step = max_step  # 步长最大值
        self._fillna = fillna  # 是否填充空值
        self._run()

    def _run(self):
        up_trend = True  # 默认初始是上升趋势
        acceleration_factor = self._step  # 初始加速因子是0.02
        up_trend_high = self._high.iloc[0]  # 初始上升趋势最高值，为第一天的最高
        down_trend_low = self._low.iloc[0]  # 初始下降趋势最低值，为第一天的最低

        self._psar = pd.Series([np.nan] * self._length, index=self._close.index)
        self._psar_up = pd.Series([np.nan] * self._length, index=self._close.index)
        self._psar_down = pd.Series([np.nan] * self._length, index=self._close.index)
        self._psar_indicator = pd.Series([np.nan] * self._length, index=self._close.index)
        self._psar_af = pd.Series([np.nan] * self._length, index=self._close.index)

        for i in range(1, self._length):
            if i < self._period:
                up_trend_high = max(self._high.iloc[i], up_trend_high)
                down_trend_low = min(self._low.iloc[i], down_trend_low)
                continue
            # print(up_trend_high, down_trend_low)

            if up_trend:
                down_trend_low = min(self._low.iloc[i], down_trend_low)

                if np.isnan(self._psar.iloc[i - 1]):  # 如果一开始是空值，上升趋势默认，min最低点
                    self._psar.iloc[i] = down_trend_low
                else:
                    self._psar.iloc[i] = self._psar.iloc[i - 1] + (  # 如果有前值，计算
                        acceleration_factor * (up_trend_high - self._psar.iloc[i - 1])
                    )
                self._psar.iloc[i] = round(self._psar.iloc[i], 2)

                if self._psar.iloc[i] > self._low.iloc[i]:  # 上升趋势中SAR大于当前最低点，则翻转
                    up_trend = False  # 表示翻转了
                    self._psar.iloc[i] = up_trend_high  # 上一周期的max最高
                    down_trend_low = self._low.iloc[i]  # 最低值是当前的最低点
                    acceleration_factor = self._step  # 加速因子重置

                else:  # 没有翻转
                    if self._high.iloc[i] > up_trend_high:  # 如果有新高
                        up_trend_high = self._high.iloc[i]  # 更新当前周期内的最高价
                        acceleration_factor = min(  # 更新加速因子
                            acceleration_factor + self._step, self._max_step
                        )
            else:  # 进入下降趋势
                up_trend_high = max(self._high.iloc[i], up_trend_high)

                self._psar.iloc[i] = self._psar.iloc[i - 1] - (  # 如果有前值，计算
                    acceleration_factor * (self._psar.iloc[i - 1] - down_trend_low)
                )
                self._psar.iloc[i] = round(self._psar.iloc[i], 2)

                if self._psar.iloc[i] < self._high.iloc[i]:  # 下降趋势中，SAR小于当前最高点，则翻转
                    up_trend = True  # 表示翻转了
                    self._psar.iloc[i] = down_trend_low  # 上一周期的min最低
                    up_trend_high = self._high.iloc[i]  # 最高值是当前的最高点
                    acceleration_factor = self._step  # 加速因子重置

                else:
                    if self._low.iloc[i] < down_trend_low:  # 如果有新低
                        down_trend_low = self._low.iloc[i]  # 更新当前周期内的最低价
                        acceleration_factor = min(  # 更新加速因子
                            acceleration_factor + self._step, self._max_step
                        )

            if up_trend:
                self._psar_up.iloc[i] = 1
                self._psar_indicator.iloc[i] = 1
            else:
                self._psar_down.iloc[i] = 1
                self._psar_indicator.iloc[i] = -1
            self._psar_af.iloc[i] = acceleration_factor

    def psar(self):
        """
        返回SAR数值
        :return:
        """
        return pd.Series(self._psar, name='psar')

def gp():
    
    df = pd.read_csv('t111.csv')
    
    df = df[['trade_time', 'open', 'high', 'low', 'close']]
    result =pd.DataFrame(columns=('夏普比率','索提诺比率','日回报波动率','最大回撤','卡玛比率','最终收益','w1','w2','w3','w4','w6', 'w7'))

    import talib as ta
    
    
    p='low'
    SAR1 = SARIndicator(df,4, 0.1, 0.2)
    df['price_SAR1'] = SAR1.psar()
    SAR1 = SARIndicator(df,4, 0.05, 0.04)
    df['price_SAR2'] = SAR1.psar()
    # df['B_up'],df['B_mid'],df['B_dn'] = ta.BBANDS(df['low'], timeperiod = 4, matype = 1)
    df['BBI'] = (ta.MA(df[p],2)+ta.MA(df[p],4)+ta.MA(df[p],8)+ta.MA(df[p],16))/4 
    for w1 in [2,4,6,12,24]:#:
        for w2 in [6]:
            df['price_SAR_ma1'] = ta.MA(df['price_SAR1'],w1,w2)
            df['price_SAR_ma'] = ta.MA(df['price_SAR2'],w1,w2)
            df['B_up'],df['B_mid'],df['B_dn'] = ta.BBANDS(df['low'], timeperiod = w1, matype = w2)
            
                    
            # 设置回测周期
            import matplotlib.pyplot as plt
        
            aa = 2
            # #上下穿信号
            总手数 = 1
            
            收益杠杆 = 10000
            # [2,4,6,12,24,  ]:#
            df['单位时间涨跌s'] = (df['close']-df['close'].shift(1)) * 收益杠杆 
            for w3 in [2,4,6,12,24]:#range(2,30,2):
                for w4 in [2,4,6,12,24]:#:
                    for w6 in [2,4,6,12,24]:#:
                        for w7 in [2,4,6,12,24]:#:
                            # for w5 in [1]:#[-1,1]:
                                # if w3!=w4:
                            df['SAR_signal_cross1'] = 0
                            df['SAR_signal_cross1'][(df['high'] == (df['high'].rolling(w6).max()))] = 总手数*(-1)
                            
                            df['SAR_signal_cross4']=0
                            df['SAR_signal_cross4'][(df['low'] == (df['low'].rolling(w7).min()))] = 总手数*(1)
                        
                            df['SAR_signal_cross2'] = 0
                            df['SAR_signal_cross2'][(df['price_SAR_ma1'] == (df['price_SAR_ma1'].rolling(w3).max()))] = 总手数*(-1)
                            df['SAR_signal_cross2'][(df['price_SAR_ma1'] == (df['price_SAR_ma1'].rolling(w4).min()))] = 总手数*(1)
                            
                            df['SAR_signal_cross3'] = 0
                            df['SAR_signal_cross3'][((df['price_SAR_ma'] < df['B_mid']))&(df['price_SAR_ma1'] > df['BBI'])] = 总手数*(-1)
                            df['SAR_signal_cross3'][((df['price_SAR_ma'] > df['B_mid']))&(df['price_SAR_ma1'] < df['BBI'])] = 总手数*(1)
                            
                            df['总信号'] = 0
                            df['总信号'][(df['SAR_signal_cross1'] + df['SAR_signal_cross2']+df['SAR_signal_cross3']+df['SAR_signal_cross4'])>(0)] = 1
                            df['总信号'][(df['SAR_signal_cross1'] + df['SAR_signal_cross2']+df['SAR_signal_cross3']+df['SAR_signal_cross4'])<(0)] = -1
                            
                            df['总信号']=df['总信号'].mask(df['总信号'] == 0).ffill()
                            df['单位时间涨跌1s'] = df['单位时间涨跌s'] * (df['总信号'].shift(aa))
                            
                            df['止损'] = -200 * ((df['总信号'].shift(aa)).abs())
                            df['手续费'] = 3
                            
                            df['单位时间收益'] = 0
                            df['单位时间跌幅s'] = 0
                            df['单位时间跌幅s'][df['总信号'].shift(aa)<0] = (df['close'].shift(1) - df['high'])*((df['总信号'].shift(aa)).abs())* 收益杠杆
                            df['单位时间跌幅s'][df['总信号'].shift(aa)>0] = (df['low'] - df['close'].shift(1))*((df['总信号'].shift(aa)).abs())* 收益杠杆
                            
                             
                            for i in range(5,len(df)):  
                                if df['总信号'][i-aa]!=0:
                                    df['单位时间收益'][i] = (df['单位时间涨跌1s'][i])#*(df['sumret'][i-1]//20000)
                                    if ((df['单位时间跌幅s'][i]) <= df['止损'][i]):
                                        df['单位时间收益'][i] = (df['止损'][i]-df['手续费'][i])#*(df['sumret'][i-1]//20000)
                            
                            df['单位时间收益1'] = df['单位时间收益']
                            df['单位时间收益1'][(df['总信号'].shift(aa)!=df['总信号'].shift(aa+1))]=df['单位时间收益1']-3
                            
                            # df['单位时间收益1'] = 0
                            # df['单位时间收益1'][(df['单位时间收益']!=0)] = df['单位时间收益']
                            # df['单位时间收益1'][(df['总信号'].shift(aa)!=df['总信号'].shift(aa+1)) & (df['单位时间收益']!=0)] = df['单位时间收益']-3
                            # df['单位时间收益1'][(df['单位时间收益']!=0) & (df['单位时间收益']==-200) & (df['单位时间跌幅s']<=-200)] = df['单位时间收益']-3
                            df['单位时间收益1'][df['trade_time'].str.contains('13:05')==True]= 0
                            df['单位时间收益1'][df['trade_time'].str.contains('09:20')==True]= 0
                            df['单位时间收益1'][df['trade_time'].str.contains('11:30')==True]= 0
                            df['单位时间收益1'][df['trade_time'].str.contains('15:15')==True]= 0
         
                             
                                
                            df['sumret'] = df['单位时间收益1'].cumsum(axis = 0)
                            df['sumret'] = (df['sumret'] +20000)
                            df['win'] = 0
                            df['lose'] = 0
                            df['win'][df['单位时间收益1']>0] = 1
                            df['lose'][df['单位时间收益1']<0] = 1
                            
                            win_rate = (df['win'].sum())/len(df)
                            lose_rate = (df['lose'].sum())/len(df)
                            
                            # if (win_rate/(win_rate+lose_rate)) > 0.5:
                            plt.rcParams['font.sans-serif']=['SimHei']  #显示中文标签
                            plt.rcParams['axes.unicode_minus']=False   #这两行需要手动设置
                            
                            from matplotlib.pyplot import savefig
                            plt.ion()
                            fig=plt.figure(figsize=(14,6))
                            ax1=fig.add_subplot(111)
                            ax1.plot(df['sumret'],'b-',label='交易回测',linewidth=2)
                            ax2=ax1.twinx()#这是双坐标关键一步
                            ax2.plot(df['close'],'r-',label='T.CFX',linewidth=2)
                            df1 = df.loc[df['trade_time'].str.contains('15:15')]
                            df1 = df1.reset_index(drop=True)
                            df1 = df1[['trade_time','sumret']]
                            df1['daily_ret'] = df1['sumret'].pct_change()
                            df1['excess_daily_ret'] = df1['daily_ret'] - 0.03/365
                            # SR = np.sqrt(250) * df1['excess_daily_ret'].mean() / df1['excess_daily_ret'].std()
                            
                            
                            def sortino_ratio(series):
                                r = series / series.shift(1) - 1
                                r = r.dropna()
                                sr = np.sqrt(252) * (r.mean()) / np.std(r[r < 0.027/365])
                                return sr
                            
                            def return_volatility(series):
                                return_pcnt = series.pct_change(1)
                                volatility = np.std(return_pcnt)
                                return volatility
                            
                            def maximum_drawdown(series):
                                performance_list = list(series)
                                i = np.argmax(np.maximum.accumulate(performance_list) - performance_list)
                                j = np.argmax(performance_list[:i])
                                mdd = (performance_list[i] - performance_list[j]) / performance_list[j]
                                return mdd
                            
                            def calmar_ratio(series):
                                r = series / series.shift(1) - 1
                                r = r.dropna()
                            
                                mdd = maximum_drawdown(series)
                            
                                return np.sqrt(252) * (r.mean()) / abs(mdd)
                            
                            
                            
                            夏普比率 = round(np.sqrt(250) * df1['excess_daily_ret'].mean() / df1['excess_daily_ret'].std(), 4)
                            索提诺比率 = round(sortino_ratio(df1['sumret']), 4)
                            日回报波动率 = round(return_volatility(df1['sumret']), 4)
                            最大回撤 = round(maximum_drawdown(df1['sumret']),4)
                            卡玛比率 = round(calmar_ratio(df1['sumret']),4)
                            
                            result=result.append(pd.DataFrame({'夏普比率':[夏普比率],'索提诺比率':[索提诺比率],'日回报波动率':[日回报波动率],'最大回撤':[最大回撤],'卡玛比率':[卡玛比率],'最终收益':[round((df['sumret'].values[-1])/10000,2)],'w1':[w1],'w2':[w2],'w3':[w3],'w4':[w4],'w6':[w6], 'w7':[w7]}),ignore_index=True)
                            savefig('D:/新建文件夹/ma6/'+ str(夏普比率)+'-P'+str(round((df['sumret'].values[-1])/10000,2))+ '-'+  str(round(win_rate/(win_rate+lose_rate),2))+'-'+str(w1)+ '-' +str(w2)+ '-'+ str(w3)+ '-' +str(w4)+ '-'+  str(w6)+ '-' +str(w7) +'.jpg')
                            # savefig('D:/新建文件夹/224/'+ str(round(SR,2))+'-P'+str(round((df['sumret'].values[-1])/10000,3))+ '-'+  str(round(win_rate/(win_rate+lose_rate),3))+'-'+str(w1)+ '-' +str(w2)+ '-'+ str(w3)+ '-' +str(w4)+ '-'+  str(w6)+ '-'+  str(w7) +'.jpg')#+ '-'+ str(i5)+ '-'+  str(i6)+'-'+str(i7)+ '-'+str(i8)+ '-'+str(i9)+'-'+str(i10)+ '-'+str(i11)+ '-'+str(i12)+ '-' +'.jpg')
                            
                            plt.pause(0.5)
                            plt.close()
                            # savefig('D:/新建文件夹/222/'+str(round((df['sumret'].values[-1])/10000,3))+ '-w'+  str(round(win_rate/(win_rate+lose_rate),3))+'-'+ str(w1)+ '-' +str(w2)+ '-'+ str(w3)+ '-' +str(w4)+ '-'+  str(w5)+ '-' +str(w6)+ '-'+  str(w7) +'.jpg')#+ '-'+ str(i5)+ '-'+  str(i6)+'-'+str(i7)+ '-'+str(i8)+ '-'+str(i9)+'-'+str(i10)+ '-'+str(i11)+ '-'+str(i12)+ '-' +'.jpg')
    result.to_excel('D:/新建文件夹/ma6.xlsx')